import Cookies from 'js-cookie'
import {forEach, hasOneOf} from '@/libs/tools'
// cookie保存的天数
import config from '@/conf'

export const setToken = (key, token) => {
  Cookies.set(key, token, {expires: config.cookieExpires || 1})
}

export const getToken = (key) => {
  const token = Cookies.get(key)
  if (token) return token
  else return false
}

/**
 * 获取JSON所有父级节点
 * @param arr {Array} 传递的JSON数组对象
 * @param id {Number | String} 当前子节点id
 * @param idProperty { String } 判断的字段名称
 * @param childProperty { String } 遍历子元素的字段名称
 * @returns {{}}
 */
export const findParentsNode = (arr, id, idProperty = 'treeID', childProperty = 'children') => {
  let parents = []
  let index = 0
  let hasParentId = (function loop (arr, index) {
    return arr.some((item) => {
      if (item[idProperty] === id) {
        parents = parents.slice(0, index)
        return true
      } else if (Array.isArray(item[childProperty])) {
        parents[index] = item
        return loop(item[childProperty], index + 1)
      } else {
        return false
      }
    })
  }(arr, index))
  return hasParentId ? parents : []
}
/**
 * 获取JSON父级节点
 * @param arr {Array} 传递的JSON数组对象
 * @param id {Number | String} 当前子节点id
 * @param emptySelf {Boolean} [true]
 * @param childProperty { String } [children] 遍历子元素的字段名称
 * @param idProperty { String } [treeID] 判断的字段名称
 * @returns {json} [parentNode | selfNode] 如果没有父级默认返回自身节点
 */
export const findParentNode = (arr, id, emptySelf = true, childProperty = 'children', idProperty = 'treeID') => {
  let parentNode = null
  let selfNode = null;
  (function loop (arr) {
    return arr.some((item) => {
      if (item[idProperty] === id) {
        selfNode = item
        return true
      } else if (Array.isArray(item[childProperty])) {
        let flag = false
        item[childProperty].forEach(e => { if (e[idProperty] === id) flag = true })
        if (flag) parentNode = item
        return loop(item[childProperty])
      } else {
        return false
      }
    })
  }(arr))
  return parentNode || ((emptySelf && selfNode) || {})
}

/**
 * JSON插入数据
 * @param arr {Array} 传递的JSON数组对象
 * @param id {Number | String} 要插入数据的父级id
 * @param val {data} 插入的数据
 * @param childProperty { String } [children] 遍历子元素的字段名称
 * @param idProperty { String } [treeID] 判断的字段名称
 * @returns {json} [parentNode | selfNode] 如果没有父级默认返回自身节点
 */
export const jsonAppend = (arr, id, val, idProperty = 'treeID', childProperty = 'children') => {
  return (function loop (arr) {
    return arr.map((item) => {
      if (item[idProperty] === id) {
        if (!Array.isArray(item[childProperty])) item[childProperty] = []
        item[childProperty].push(val)
      } else if (Array.isArray(item[childProperty])) {
        item.children = loop(item[childProperty])
      }
      return item
    })
  }(arr))
}

/**
 * JSON数据更新
 * @param arr {Array} 传递的JSON数组对象
 * @param id {Number | String} 要插入数据的父级id
 * @param val {data} 插入的数据
 * @param emptySelf {Boolean} [true]
 * @param childProperty { String } [children] 遍历子元素的字段名称
 * @param idProperty { String } [treeID] 判断的字段名称
 * @returns {json} [parentNode | selfNode] 如果没有父级默认返回自身节点
 */
export const updateJSON = (arr, id, val, idProperty = 'treeID', childProperty = 'children') => {
  return (function loop (arr) {
    return arr.map((item) => {
      if (item[idProperty] === id) {
        if (!Array.isArray(item[childProperty])) item[childProperty] = []
        return Object.assign(item, val)
      } else if (Array.isArray(item[childProperty])) {
        item.children = loop(item[childProperty])
      }
      return item
    })
  }(arr))
}

/**
 * 获取兄弟节点
 * @param arr
 * @param level
 * @param val
 * @param emptySelf
 * @param childProperty
 * @returns {Array}
 */
export const getJSONSiblings = (arr, level, val, emptySelf = true, childProperty = 'children') => {
  let temp = [];
  (function loop (arr) {
    arr.forEach(e => {
      if (e.level === level) temp.push(e)
      if (Array.isArray(e[childProperty])) loop(e[childProperty])
    })
  })(arr)
  return temp
}

/**
 * 获取兄弟节点
 * @param arr
 * @param id
 * @param emptySelf
 * @param childProperty
 * @param idProperty
 * @returns {Array}
 */
export const getJSONNode = (arr, id, emptySelf = true, childProperty = 'children', idProperty = 'treeID') => {
  let temp = {};
  (function loop (arr) {
    arr.forEach(e => {
      if (e[idProperty] === id) {
        temp = e
        return true
      }
      if (Array.isArray(e[childProperty])) loop(e[childProperty])
    })
  })(arr)
  return temp
}

/**
 * 移动节点
 * @param arr
 * @param id
 * @param parentID
 * @param emptySelf
 * @param childProperty
 * @param idProperty
 */
export const moveJSONNode = (arr, id, parentID, emptySelf = true, childProperty = 'children', idProperty = 'treeID') => {
  let val = getJSONNode(arr, id, true, childProperty, idProperty)
  return jsonAppend(removeJSONNode(arr, id, idProperty, childProperty), parentID, val, idProperty, childProperty)
}

/**
 * 删除节点 (不支持循环删除需要迭代遍历)
 * @param arr
 * @param id
 * @param childProperty
 * @param idProperty
 * @returns {Array}
 */
export const removeJSONNode = (arr, id, idProperty = 'treeID', childProperty = 'children') => {
  return (function loop (arr) {
    return arr.filter((item) => {
      if (item[idProperty] === id) {
        return false
      } else if (Array.isArray(item[childProperty])) {
        item[childProperty] = loop(item[childProperty])
      }
      return true
    })
  })(arr)
}

/**
 * 转一维数组 (不支持循环删除需要迭代遍历)
 * @param arr
 * @param childProperty
 * @returns {Array}
 */
export const jsonToFlat = (arr, childProperty = 'children') => {
  let temp = [];
  (function loop (arr) {
    return arr.forEach((item) => {
      temp.push(item)
      if (Array.isArray(item[childProperty])) {
        loop(item[childProperty])
      }
    })
  })(arr)
  return temp
}

export const $check = {
  isHttps () { return document.location.protocol === 'https:' },
  isSsl () { return /^ssl./i.test(document.location.host) },
  isIpad () { return /ipad/i.test(navigator.userAgent.toLowerCase()) },
  isQQ (t) { return /^[1-9]{1}\d{4,9}$/.test(t) },
  isNullQQ (str) { return /^\d{1,4}$/.test(str) },
  isNick (str) { return /^[a-zA-Z]{1}([a-zA-Z0-9]|[-_]){0,19}$/.test(str) },
  isName (str) { return name !== '<请输入帐号>' && /[\u4E00-\u9FA5]{1,8}/.test(str) },
  isPhone (str) { return /^(?:86|886|)1\d{10}\s*$/.test(str) }, // 手机号支持区号
  isSeaPhone (str) { return /^(00)?(?:852|853|886(0)?\d{1})\d{8}$/.test(str) }, // 固话
  isMail (str) { return /^\w+((-\w+)|(\.\w+))*@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/.test(str) },
  isQQMail (str) { return /^[1-9]{1}\d{4,9}@qq\.com$/.test(str) },
  isQiyeQQ800 (str) { return /^(800)\d{7}$/.test(str) }, // 800企业开头号码
  isForeignPhone (str) { return /^00\d{7,}/.test(str) }, // 国外号码
  isNumLetter (str) { return /^[0-9a-zA-Z]*$/g.test(str) }
}

export const hasChild = (item) => {
  return item.children && item.children.length !== 0
}

const showThisMenuEle = (item, access) => {
  if (item.meta && item.meta.access && item.meta.access.length) {
    if (hasOneOf(item.meta.access, access)) return true
    else return false
  } else return true
}
/**
 * @param {Array} list 通过路由列表得到菜单列表
 * @returns {Array}
 */
export const getMenuByRouter = (list, access) => {
  let res = []
  forEach(list, item => {
    if (item.meta && !item.meta.hideInMenu) {
      let obj = {
        icon: (item.meta && item.meta.icon) || '',
        name: item.name,
        meta: item.meta
      }
      if (hasChild(item) && showThisMenuEle(item, access)) {
        obj.children = getMenuByRouter(item.children, access)
      }
      if (showThisMenuEle(item, access)) res.push(obj)
    }
  })
  return res
}

/**
 * @param {Array} routeMetched 当前路由metched
 * @returns {Array}
 */
export const getBreadCrumbList = (routeMetched) => {
  let res = routeMetched.map(item => {
    let obj = {
      icon: (item.meta && item.meta.icon) || '',
      name: item.name,
      meta: item.meta
    }
    return obj
  })
  res = res.filter(item => {
    return !item.meta.hideInMenu
  })
  return [{
    name: 'home',
    to: '/home'
  }, ...res]
}

export const showTitle = (item, vm) => vm.$config.useI18n ? vm.$t(item.name) : ((item.meta && item.meta.title) || item.name)

/**
 * @description 本地存储和获取标签导航列表
 */
export const setTagNavListInLocalstorage = list => {
  localStorage.tagNaveList = JSON.stringify(list)
}
/**
 * @returns {Array} 其中的每个元素只包含路由原信息中的name, path, meta三项
 */
export const getTagNavListFromLocalstorage = () => {
  const list = localStorage.tagNaveList
  return list ? JSON.parse(list) : []
}

/**
 * @param {Array} routers 路由列表数组
 * @description 用于找到路由列表中name为home的对象
 */
export const getHomeRoute = routers => {
  let i = -1
  let len = routers.length
  let homeRoute = {}
  while (++i < len) {
    let item = routers[i]
    if (item.children && item.children.length) {
      let res = getHomeRoute(item.children)
      if (res.name) return res
    } else {
      if (item.name === 'home') homeRoute = item
    }
  }
  return homeRoute
}

/**
 * @param {*} list 现有标签导航列表
 * @param {*} newRoute 新添加的路由原信息对象
 * @description 如果该newRoute已经存在则不再添加
 */
export const getNewTagList = (list, newRoute) => {
  const { name, path, meta } = newRoute
  let newList = [...list]
  if (newList.findIndex(item => item.name === name) >= 0) return newList
  else newList.push({ name, path, meta })
  return newList
}

/**
 * @param {Boolean} status 状态 1 => locked  0 => unlocked
 * @description 这里只是为了演示，实际应该将锁定状态的设置和获取用接口来实现
 */
export const setLockStatus = (status) => {
  localStorage.isLocked = status
}
export const getLockStatus = () => {
  return parseInt(localStorage.isLocked)
}

/**
 * @param {*} access 用户权限数组，如 ['super_admin', 'admin']
 * @param {*} route 路由列表
 */
const hasAccess = (access, route) => {
  if (route.meta && route.meta.access) return hasOneOf(access, route.meta.access)
  else return true
}

/**
 * @param {*} name 即将跳转的路由name
 * @param {*} access 用户权限数组
 * @param {*} routes 路由列表
 * @description 用户是否可跳转到该页
 */
export const canTurnTo = (name, access, routes) => {
  const getHasAccessRouteNames = (list) => {
    let res = []
    list.forEach(item => {
      if (item.children && item.children.length) {
        res = [].concat(res, getHasAccessRouteNames(item.children))
      } else {
        if (item.meta && item.meta.access) {
          if (hasAccess(access, item)) res.push(item.name)
        } else {
          res.push(item.name)
        }
      }
    })
    return res
  }
  const canTurnToNames = getHasAccessRouteNames(routes)
  return canTurnToNames.indexOf(name) > -1
}

/**
 * @param {String} url
 * @description 从URL中解析参数
 */
export const getParams = url => {
  const keyValueArr = url.split('?')[1].split('&')
  let paramObj = {}
  keyValueArr.forEach(item => {
    const keyValue = item.split('=')
    paramObj[keyValue[0]] = keyValue[1]
  })
  return paramObj
}

/**
 * @param {Array} list 标签列表
 * @param {String} name 当前关闭的标签的name
 */
export const getNextName = (list, name) => {
  let res = ''
  if (list.length === 2) {
    res = 'home'
  } else {
    if (list.findIndex(item => item.name === name) === list.length - 1) res = list[list.length - 2].name
    else res = list[list.findIndex(item => item.name === name) + 1].name
  }
  return res
}

/**
 * @description 普通文件上传地址
 * @param FileType 文件类型
 */
export const setUploadUrl = (FileType) => {
  let url = config.baseURL + '/Common/Tool/DPMFileUpLoad'
  if (FileType) url = config.baseURL + '/Common/Tool/DPMFileUpLoad?FileType=' + FileType
  return url
}

/**
 * @description 批量导入的上传地址
 * @param type 1为导入员工 2为导入账号
 */
export const setImportUrl = (type) => {
  let url = ''
  if (type === 1) url = config.baseURL + '/DPM/Employee/ImportEmployee'
  else if (type === 2) url = config.baseURL + '/DPM/MediaAccount/ImportMediaAccount'
  return url
}

/**
 * @description 本地存储权限数组
 */
export const setLocalPermission = (list) => {
  localStorage.permissions = JSON.stringify(list)
}

/**
 * @description 根据用户权限信息：rolePermission（嵌套数组）去判断模块或功能的进入/操作等权限
 * @param permissionArray 用户权限数组
 * @param key 权限唯一id
 */
export const getAccess = (array, key) => {
  let access = false
  let permissionArray = array ? JSON.parse(array) : []
  for (let item of permissionArray) {
    if (item.PermissionID === key) {
      access = true
      break
    } else {
      access = false
    }
  }
  return access
}

/**
 * @description 清除cookies
 */
export const clearCookie = () => {
  let keys = document.cookie.match(/[^ =;]+(?=)/g)
  if (keys) {
    for (let i in keys) {
      document.cookie = keys[i] + '=0;expires=' + new Date(0).toUTCString()
    }
  }
}

/**
 * @description 清除指定keys的本地存储
 * @param keys 键值数组
 */
export const clearLocalStorageByKeys = (keys = ['tagNavList', 'permissions']) => {
  for (let item of keys) {
    localStorage.removeItem(item)
  }
}

/**
 * 生成随机数
 * @returns {*}
 * @private
 */
export function randomStr (str) {
  // toString() 2~36    10+26字母[A-Z 0-9]  36个字符
  return Math.random().toString(36).substr(2)
}

/**
 * 将长整形转换为string,private
 * @returns {*}
 * @private
 */
export function SYEncrypt (privateKey) {
  this._keyString = privateKey
}

// function: encrypt str with private key by custom
SYEncrypt.prototype.encrypt = function (str) {
  if (str === '') return ''
  let tmp = ''
  for (let s of this._keyString) tmp += (str % s.charCodeAt()).toString(36)
  return tmp
}

/**
 * 鉴权函数
 * @param global 全局对象【__global_yoonasy_xxxz】
 * @param configure Axios参数
 * @returns {*}
 */
export function tokenProcess (global, configure) {
  if (global) {
    let t = +Date.now().toString().slice(0, 10) + global.difference
    let s0 = ((t * 2 % 16432) * (t * 2 % 16432)) % 100000
    let str = global.originStr
    configure += `&cp=${str}&sp=${new SYEncrypt(str).encrypt(s0)}`
  } else {
    let reRes = /ckt=(\d+)/g.exec(document.cookie)
    if (reRes.length > 1) {
      let serverStamp = parseInt(reRes[1])
      let localStamp = Date.now().toString().slice(0, 10)
      window.__global_yoonasy_xxxz = {
        difference: serverStamp - localStamp,
        originStr: randomStr()
      }
      return tokenProcess(global, configure)
    } else {
      window.__global_yoonasy_xxxz = {}
    }
  }
  return configure
}
